Firebird - rychlost insertu

Otázka od: Tomas Bradle

28. 8. 2004 13:42

Zdravim vsechny,

mam aplikaci, ktera zapisuje do protokolu hlaseni o sve cinnosti - do tabuly
ERRLOG se sloupecky ID(integer), TS(timestamp), MSG(varchar). Behem
zkusebniho provozu (cca 3 tydny) se tam nahromadilo cca 65 tis. zaznamu. Na
before insert triggeru mam mechanizmus zjistovani, jestli zaznam se stejnym
ID jiz existuje

DECLARE VARIABLE CNT INTEGER;
BEGIN
IF (NEW.ID IS NULL) THEN
  NEW.ID=gen_id(ID_ERRLOG, 1)*100+STATION_ID();
SELECT COUNT(*) FROM ERRLOG WHERE ID=NEW.ID INTO :CNT;
IF (:CNT > 0) THEN
  NEW.ID=-1;
END

a v after insert triggeru mam

DELETE FROM ERRLOG WHERE ID=-1;

tato kombinace prakticky zpusobi, ze pokus o vlozeni jiz existujiciho
zaznamu bude ignorovan. To je jev, ktery se vzhledem k povaze aplikace muze
vyskytnout cca jedenkratza 500-1000 zaznamu a nelze (!!!) jej vyloucit (je
to pripad, kdy (NEW.ID IS NOT NULL)).

Pri odmerovani doby vykonavani jednotlivych insertu (kazdy insert je
samozrejme v samostatne transakci) mi vysla doba cca 800 ms. Po vymazani cca
30 tis zaznamu z cela tabulky (tech nejstarsich) se zkratila doba cca na 200
ms.

Mam dotazy:

1. jaky je duvod tohoto zkraceni ? - chtel bych lepe pochopit cinnost FB

2. je mi jasne, ze uvedeny SELECT count(*) muze byt zasove narocny (?),
existuje neco rychlejsiho ? (o moznosti nechat to spadnout na exception
uvazuji)

3. chci samozrejme udelat nejake automaticke odmazavani, jeste jsem se
nerozhodl jak - jaka by byla nejlepsi metoda ?


diky

Tomas Bradle
t.bradle@worldonline.cz


Odpovedá: Jakub Dusek

28. 8. 2004 14:06

Pole ID tabulky ERRLOG je primarni klic? Pokud ne, je na nej vytvoren
index?

Jakub Dusek
----------------------------------------------------------------------
web: http://www.corexpert.com, mobile: +420 604 615 795, ICQ: 86063232
odesilani smsek, vizitek, log a melodii, snadna integrace do Vaseho IS
     => Sms GateKeeper, Sms GateKeeper Service

======================================================================
Saturday, August 28, 2004, 2:42:04 PM, you wrote:

TB> SELECT COUNT(*) FROM ERRLOG WHERE ID=NEW.ID INTO :CNT;



Odpovedá: Tomas Bradle

28. 8. 2004 14:38

No jo, ja tam ten index opravdu nemam, myslel jsem, ze jo a nenapadlo me se
podivat, takze jako u 90% zavad, zase nejaka "blbost"...

Ted uz je to cca 20 ms.

diky

Tomas Bradle
t.bradle@worldonline.cz


----- Original Message -----
From: "Jakub Dusek" <delphi@corexpert.com>
To: <delphi-l@clexpert.cz>
Sent: Saturday, August 28, 2004 3:06 PM
Subject: Re: Firebird - rychlost insertu


> Pole ID tabulky ERRLOG je primarni klic? Pokud ne, je na nej vytvoren
> index?
>
> Jakub Dusek
>



Odpovedá: Tomas Michalik

28. 8. 2004 17:32

Tomas Bradle wrote:

> Zdravim vsechny,
>
> mam aplikaci, ktera zapisuje do protokolu hlaseni o sve cinnosti - do tabuly
> ERRLOG se sloupecky ID(integer), TS(timestamp), MSG(varchar). Behem
> zkusebniho provozu (cca 3 tydny) se tam nahromadilo cca 65 tis. zaznamu. Na
> before insert triggeru mam mechanizmus zjistovani, jestli zaznam se stejnym
> ID jiz existuje
>
> DECLARE VARIABLE CNT INTEGER;
> BEGIN
> IF (NEW.ID IS NULL) THEN
> NEW.ID=gen_id(ID_ERRLOG, 1)*100+STATION_ID();
> SELECT COUNT(*) FROM ERRLOG WHERE ID=NEW.ID INTO :CNT;
> IF (:CNT > 0) THEN
> NEW.ID=-1;
> END

Tam, kde nemusis, se nezdrzuj volanim "select count(*)", ale pouzij
konstrukci "if exists"

BEGIN
IF (NEW.ID IS NULL) THEN
   NEW.ID=gen_id(ID_ERRLOG, 1)*100+STATION_ID();
   if (exists (select *
               from ERRLOG
               where WHERE ID=NEW.ID)) then
     NEW.ID=-1;
END

========================
Tomas Michalik
vyvoj IS

ProCA, spol. s r.o.
V Luzich 818
Praha 4 - Libus
140 00, Czech Republic

tel: +420 234646446
fax: +420 234646120

michalik@proca.cz
http://www.proca.cz


Odpovedá: Slavomir Skopalik

29. 8. 2004 12:57

Me se ta kontrukce vubec nelibi.
Proc slozite testuji, vkladam a pak zase mezu, kdyz to jde velmi
jednoduse.

1. Bud mohu nechat vkladani spadnout na vyjimku a tu osetrit na urovni
aplikace
2. Nebo mohu si napsat uloznou proceduru asi takto

begin
  BEGIN
    INSERT INTO DeviceData(idDevMeasurandLimit,tValue)VALUES(0,'---');
    WHEN ANY DO i=1;
  END
end^

Nad ID je samopzrejme primarni klic, ktery provede testy na duplicitu.
 

 Slavek
     
>
> DECLARE VARIABLE CNT INTEGER;
> BEGIN
> IF (NEW.ID IS NULL) THEN
> NEW.ID=gen_id(ID_ERRLOG, 1)*100+STATION_ID();
> SELECT COUNT(*) FROM ERRLOG WHERE ID=NEW.ID INTO :CNT;
> IF (:CNT > 0) THEN
> NEW.ID=-1;
> END
>
> a v after insert triggeru mam
>
> DELETE FROM ERRLOG WHERE ID=-1;
>
> tato kombinace prakticky zpusobi, ze pokus o vlozeni jiz
> existujiciho zaznamu bude ignorovan. To je jev, ktery se
> vzhledem k povaze aplikace muze vyskytnout cca jedenkratza
> 500-1000 zaznamu a nelze (!!!) jej vyloucit (je to pripad,
> kdy (NEW.ID IS NOT NULL)).
>
> Pri odmerovani doby vykonavani jednotlivych insertu (kazdy
> insert je samozrejme v samostatne transakci) mi vysla doba
> cca 800 ms. Po vymazani cca 30 tis zaznamu z cela tabulky
> (tech nejstarsich) se zkratila doba cca na 200 ms.


Odpovedá: Tomas Bradle

30. 8. 2004 11:04

No, nedovedu si predstavit 20 procedur pro 20 tabulek, ale na urovni
aplikace by to snad slo, ted jde jenom o to, jak odlisit chybu primarniho
klice od jinych chyb (nerad bych zahodil platny zaznam, ktery ma byt vlozen,
ale vznikla jina exception)

diky
Tomas

----- Original Message -----
From: "Slavomir Skopalik" <skopalik@elektlabs.cz>
To: <delphi-l@clexpert.cz>
Sent: Sunday, August 29, 2004 1:57 PM
Subject: Re: Firebird - rychlost insertu


> Me se ta kontrukce vubec nelibi.
> Proc slozite testuji, vkladam a pak zase mezu, kdyz to jde velmi
> jednoduse.
>
> 1. Bud mohu nechat vkladani spadnout na vyjimku a tu osetrit na urovni
> aplikace
> 2. Nebo mohu si napsat uloznou proceduru asi takto
>
> begin
> BEGIN
> INSERT INTO DeviceData(idDevMeasurandLimit,tValue)VALUES(0,'---');
> WHEN ANY DO i=1;
> END
> end^
>
>


Odpovedá: Slavomir Skopalik

30. 8. 2004 12:01

Muzes se nadefinovat vlastni exception a pak parsovat exception message.
Treba takto:

except
      on E:Exception do begin
        if pos('Duplicite serial number',E.Message)<>0then
Sender.EventResult:=_erIdentNumber else Sender.EventResult:=_erDB;
        s:=E.Message;

Tim si zarucis osetreni pouze tvoji exception.
Pozor, ve FB je chyba a misto nazvu exception se zobrazuje jeji poradove
cislo, takze musis testovat text.

 Slavek

> No, nedovedu si predstavit 20 procedur pro 20 tabulek, ale na
> urovni aplikace by to snad slo, ted jde jenom o to, jak
> odlisit chybu primarniho klice od jinych chyb (nerad bych
> zahodil platny zaznam, ktery ma byt vlozen, ale vznikla jina
> exception)
>
> diky
> Tomas